package com.yfs.cloud.commons;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
* @Company: 影法師工作室
* @Description: 全局异常处理器, 和 ResponseHandler 之间的关系是一个处理正常情况, 一个处理异常情况
* @author 影法師  
* @date 2020年8月24日 下午4:12:33 
* @version V1.0
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	/**
	* @Description: 捕获系统异常(即非业务异常) , 例如 json 解析异常 
	* @author 影法師 
	* @date 2020年8月25日 上午11:48:09 
	* @version V1.0 
	* @param @param e
	* @param @param request
	* @param @return    
	* @return Result    
	* @throws
	 */
	@ResponseStatus(HttpStatus.OK) // 返回给前端状态码依旧是 200
	@ExceptionHandler(Throwable.class)
	public Result handleThrowable(Throwable e, HttpServletRequest request) {
		logger.error("URL : {}, 系统异常: {}", request.getRequestURI(), e);
		return Result.fail(ResultCode.SYSTEM_ERROR);
	}

	/**
	* @Description: 捕获业务异常, 例如用户不存在这种 
	* @author 影法師 
	* @date 2020年8月25日 上午11:48:28 
	* @version V1.0 
	* @param @param e
	* @param @param request
	* @param @return    
	* @return Result    
	* @throws
	 */
	@ResponseStatus(HttpStatus.OK)
	@ExceptionHandler(BusinessException.class)
	public Result handleBusinessException(BusinessException e, HttpServletRequest request) {
		logger.info("URL : {}, 业务异常 : {}", request.getRequestURI(), e);
		return Result.fail(e.getCode(), e.getMsg());
	}

	/**
	* @Description: 捕获参数校验异常, 例如前端最常见的 400 请求 
	* @author 影法師 
	* @date 2020年8月25日 上午11:48:41 
	* @version V1.0 
	* @param @param e
	* @param @param request
	* @param @return    
	* @return Result    
	* @throws
	 */
	@ResponseStatus(HttpStatus.OK)
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
		String msg = handleFieldError(e.getBindingResult().getFieldErrors());
		logger.info("URL : {}, 参数校验异常 : {}", request.getRequestURI(), msg);
		return Result.fail(ResultCode.PARAM_IS_INVALID.getCode(), msg);
	}

	/**
	* @Description: 捕获业务断言异常 
	* @author 影法師 
	* @date 2020年8月25日 上午11:48:59 
	* @version V1.0 
	* @param @param e
	* @param @param request
	* @param @return    
	* @return Result    
	* @throws
	 */
	@ResponseStatus(HttpStatus.OK)
	@ExceptionHandler(IllegalArgumentException.class)
	public Result handleIllegalArgumentException(IllegalArgumentException e, HttpServletRequest request) {
		logger.info("URL : {}, 业务断言异常 : {}", request.getRequestURI(), e);
		return Result.fail(ResultCode.ASSERT_FAILED.getCode(), e.getMessage());
	}

	/**
	* @Description: 封装字段校验异常信息  
	* @author 影法師 
	* @date 2020年8月25日 上午11:49:08 
	* @version V1.0 
	* @param @param fieldErrors
	* @param @return    
	* @return String    
	* @throws
	 */
	private String handleFieldError(List<FieldError> fieldErrors) {
		StringBuilder sb = new StringBuilder();
		for (FieldError fieldError : fieldErrors) {
			sb.append(fieldError.getField());
			sb.append(" = [ ");
			sb.append(fieldError.getDefaultMessage());
			sb.append(" ] ");
		}
		return sb.toString();
	}

}
